////////////////////////////////////////////////////////////////////////////////
// This file is part of the Mist compiler.                                    //
//                                                                            //
// Copyright (C) 2009 The Mist project                                        //
//                                                                            //
// For a list of contributors, see the COMMITTERS file.                       //
//                                                                            //
// The Mist compiler is free software: you can redistribute it and/or modify  //
// it under the terms of the GNU General Public License as published by       //
// the Free Software Foundation, either version 3 of the License, or          //
// (at your option) any later version.                                        //
//                                                                            //
// The Mist compiler is distributed in the hope that it will be useful,       //
// but WITHOUT ANY WARRANTY; without even the implied warranty of             //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              //
// GNU General Public License for more details.                               //
//                                                                            //
// You should have received a copy of the GNU General Public License          //
// in the COPYING file. If not, see <http://www.gnu.org/licenses/>.           //
////////////////////////////////////////////////////////////////////////////////
// As a special exception, you may create a larger work that contains part or //
// all of this output source-file and distribute that work under terms of     //
// your choice, so long as that work isn't itself a compiler using this file  //
// or a modified version thereof as a file to be combined with the compiler   //
// output. Alternatively, if you modify or redistribute this source-file      //
// itself, you may (at your option) remove this special exception, which will //
// cause this file to be licensed under the GNU General Public License        //
// without this special exception.                                            //
////////////////////////////////////////////////////////////////////////////////

///
/// \file
/// Contains function composition operators.
///

#ifndef OUTPUT_FUNCTIONCOMPOSITION_HPP
#define OUTPUT_FUNCTIONCOMPOSITION_HPP

////////////////////////////////////////////////////////////////////////////////
// Includes                                                                   //
////////////////////////////////////////////////////////////////////////////////

#include <boost/function.hpp>
using boost::function;

#include <boost/lambda/lambda.hpp>
using boost::lambda::_1;
using boost::lambda::_2;

#include <boost/lambda/bind.hpp>
using boost::lambda::bind;

////////////////////////////////////////////////////////////////////////////////
// Operator Overloads                                                         //
////////////////////////////////////////////////////////////////////////////////

/// Compose the two functions \a f and \a g. Calling (f*g)(a) is the same as
/// calling f(g(a)).
///
template <class A, class B, class C>
function<A(C)> operator*(function<A(B)> f, function<B(C)> g) {
	return bind(f, bind(g, _1));
}

/// Compose the two functions \a f and \a g. Calling (f*g)(a, b) is the same as
/// calling f(g(a, b)).
///
template <class A, class B, class C1, class C2>
function<A(C1, C2)> operator*(function<A(B)> f, function<B(C1, C2)> g) {
	return bind(f, bind(g, _1, _2));
}

#endif // OUTPUT_FUNCTIONCOMPOSITION_HPP
